<?php
// Part of mmvc library, https://code.google.com/p/mmvc/
// External Dependencies: PEAR Mail-1.2.0, Net_SMTP
// Internal Dependencies: None
// Install Dependencies: apt-get install php-pear && pear install Net_SMTP && pear install Mail-1.2.0 && pear install Mail_Mime

/**
 * Helper class for sending UTF-8 email with attachment using PHP PEAR Mail and Mail_mime extensions.
 * Hides implementation details and supports disabling functionality on Windows so 
 * that the class can be used also in development environment.
 *
 * Install on Ubuntu Linux:
 * 1) sudo apt-get install php-pear
 * 2) sudo pear install Net_SMTP
 * 3) sudo pear install Mail-1.2.0
 * 4) sudo pear install Mail_Mime
 * 
 * For example, sending email using Gmail:

        $email = new Email( 'smtp', array('host'=>'ssl://smtp.gmail.com', 'port'=>'465', 'auth', 'auth'=>true, 'username'=>"testuser@gmail.com", 'password'=>'MyPassword') );
        $email->send( '"Test User" <testuser@gmail.com>', '"Receiver" <receiver@example.com>', 'Hi there', "Hi, the actualy message comes here\n" );
 
 */
class Email {
	private $backend;
	private $params;
	private $enabled;
	private $mailer = false;
	private $attachments = array();
	
	/**
	 * Last error message if any.
	 */
	private $lastError = false;
	
	/**
	 * Creates a mailer instance.
	 * @param $backend "smtp", "mail" or "sendmail"
	 * @param $params Array of params. For SMTP typical are host, port, auth, username, password
	 * @param $windows_nt Enable functionality also when running on Windows. Default is false.
	 * @see http://pear.php.net/manual/en/package.mail.mail.factory.php
	 */
	function __construct( $backend, $params, $windows_nt=false ) {
		$this->backend = $backend;
		$this->params = $params;
		$this->enabled = ( $windows_nt || getenv('OS') != 'Windows_NT' ); 
	}
	
	/**
	 * Adds attachment to the email.
	 * @param $file File content or local file name if $is_file==true
	 * @param $is_file If true then $file is local file name, if false then $file is content.
	 * @param $name File name. Used only if $is_file is false.
	 * @param $c_type The content type of the image or file
	 * @param $enc Type of transfer encoding to use for the file data. Defaults is "base64"
	 */
	function attach( $file, $is_file=true, $name='', $c_type='application/octet-stream', $enc='base64' ) {
		assert( $is_file || $name != '' );
		
		if ( $is_file && !file_exists($file) )
			throw new \Exception( sprintf('Failed to open "%s".', $file) );
		
		$this->attachments[] = array(
			'file' => $file,
			'is_file' => $is_file,
			'name' => $name,
			'c_type' => $c_type,
			'enc' => $enc,
		);
	}

	/** Removes all attachments. */
	function removeAttachments() {
		$this->attachments = array();
	}
	
	/**
	 * Sends the email. Uses previously set header fields (setField) and 
	 * @param $from Email sender. Format is following: '"Ex Ample" <ex.ample@example.com>'
	 * @param $to Email receiver. Format is following: '"Ex Ample" <ex.ample@example.com>'
	 * @param $subject Email subject field as plain text
	 * @param $body_text Email body as plain text.
	 * @param $body_html Email HTML body. If false then this field is generated from the body_text.
	 * @param $headers Other email headers: Bcc, Cc
	 */
	function send( $from, $to, $subject, $body_text, $body_html=false, $headers=array() ) {
		if ( $this->enabled ) {
			$old_err = error_reporting( -1 & ~2048 );
			require_once('Mail.php'); // if you get errors from here you don't have PEAR Mail or Mail_mime installed 
			require_once('Mail/mime.php');
			
			$mime = new \Mail_mime("\n");
			$getparams = array(
				"text_encoding" => 'UTF-8',
				"html_encoding" => 'UTF-8',
				"head_charset" => 'UTF-8',
				"text_charset" => 'UTF-8',
				"html_charset" => 'UTF-8',
			);

			$mime->setTXTBody( !$body_text ? $body_html : $body_text );
			if ( !$body_html )
				$body_html = str_replace("\n","<br/>\n",$body_text);
			$mime->setHTMLBody( $body_html );

			foreach ($this->attachments as $a) {
				$mime->addAttachment( $a['file'], $a['c_type'], $a['name'], $a['is_file'], $a['enc'] );
			}
			$body = $mime->get( $getparams );
			$headers['Subject'] = $subject;
			$headers['From'] = $from;
			$headers['To'] = $to;
			$hdr = $mime->headers( $headers );
			
			if ( $this->mailer === false )
				$this->mailer = Mail::factory( $this->backend, $this->params );
				
			$mail = $this->mailer->send( $to, $hdr, $body );
			
			$this->lastError = false;
			if ( PEAR::isError($mail) ) 
				$this->lastError = $mail->getMessage();
			
			error_reporting( $old_err );
			
			if ( $this->lastError !== false )
				throw new \Exception( 'Email: '.$this->lastError );
		}
	}
}

?>